import uuid
from datetime import datetime
from typing import List, Dict, Any, Optional

from fastapi import APIRouter, HTTPException, Depends
from loguru import logger
from pydantic import BaseModel, Field

from .common import ApiResponse, ListResponse, success_response
from .dependencies import require_auth, require_admin
from ..models.session import session_manager
from ..models.user import User
from ..query_engine.chat_instance import ChatInstance

router = APIRouter(prefix="/api/chat", tags=["chat"])


class ChatMessage(BaseModel):
    """聊天消息模型"""
    id: str = Field(description="消息ID", examples=["msg_123"])
    role: str = Field(description="消息角色", examples=["user"], enum=["user", "assistant"])
    content: str = Field(description="消息内容", examples=["你好，请帮我分析这个数据"])
    timestamp: datetime = Field(description="消息时间戳", examples=["2024-01-01T12:00:00"])
    session_id: str = Field(description="会话ID", examples=["session_123"])


class ChatRequest(BaseModel):
    """聊天请求模型"""
    message: str = Field(
        min_length=1,
        max_length=2000,
        description="用户消息内容",
        examples=["请帮我分析一下最新的销售数据趋势"]
    )
    session_id: Optional[str] = Field(
        default=None,
        description="会话ID，如果不提供将创建新会话",
        examples=["session_123"]
    )
    knowledge_base_ids: Optional[List[str]] = Field(
        default=None,
        description="指定的知识库ID列表，用于检索相关信息",
        examples=[["kb_001", "kb_002"]]
    )
    use_reranker: bool = Field(
        default=True,
        description="是否使用重排序器提高检索质量",
        examples=[True]
    )
    use_refiner: bool = Field(
        default=True,
        description="是否使用结果优化器",
        examples=[True]
    )
    top_k: Optional[int] = Field(
        default=5,
        ge=1,
        le=20,
        description="检索返回的文档数量",
        examples=[5]
    )


class SessionRequest(BaseModel):
    """会话请求模型"""
    session_id: str = Field(description="会话ID", examples=["session_123"])


class ChatResponseData(BaseModel):
    """聊天响应数据模型"""
    session_id: str = Field(description="会话ID", examples=["session_123"])
    timestamp: str = Field(description="响应时间戳", examples=["2024-01-01T12:00:00"])
    user_message: str = Field(description="用户消息", examples=["你好"])
    knowledge_base_ids: Optional[List[str]] = Field(
        default=None,
        description="使用的知识库ID列表",
        examples=[["kb_001"]]
    )


class ChatHistoryData(BaseModel):
    """聊天历史数据模型"""
    messages: List[ChatMessage] = Field(description="消息列表")
    session_id: str = Field(description="会话ID", examples=["session_123"])


# 使用通用响应模型
ChatResponse = ApiResponse[ChatResponseData]
SessionListResponse = ListResponse[Dict[str, Any]]
ChatHistoryResponse = ApiResponse[ChatHistoryData]


class ChatHistoryRequest(BaseModel):
    """聊天历史请求模型"""
    limit: int = Field(default=50, ge=1, le=100, description="返回消息数量限制", examples=[50])
    offset: int = Field(default=0, ge=0, description="分页偏移量", examples=[0])


def get_or_create_session_id(session_id: Optional[str] = None) -> str:
    """获取或创建会话ID"""
    return session_id or str(uuid.uuid4())


async def process_ai_query(question: str, session_id: str, knowledge_base_ids: Optional[List[str]] = None) -> str:
    """处理AI查询"""
    try:
        # 获取会话上下文
        chat_instance = ChatInstance(session_id)
        result = await chat_instance.query(
            query=question,
            knowledge_base_ids=knowledge_base_ids,
        )
        return result.get("response", "抱歉，我无法处理您的问题。")
    except Exception as e:
        logger.exception(f"AI查询处理失败: {e}")
        return f"抱歉，处理您的问题时出现了错误: {str(e)}"


@router.post("/",
             response_model=ChatResponse,
             summary="发送聊天消息",
             description="""
    ## 智能对话接口
    
    与AI助手进行对话，支持基于知识库的智能问答。
    
    ### 功能特点
    - 支持多轮对话，保持上下文
    - 可指定知识库进行专业领域问答
    - 智能检索和重排序，提高回答质量
    - 自动创建或使用已有会话
    
    ### 请求参数
    - **message**: 用户消息内容（1-2000字符）
    - **session_id**: 会话ID（可选，不提供时创建新会话）
    - **knowledge_base_ids**: 知识库ID列表（可选）
    - **use_reranker**: 是否使用重排序器（提高检索质量）
    - **use_refiner**: 是否使用结果优化器
    - **top_k**: 检索文档数量（1-20）
    
    ### 会话管理
    - 如果提供session_id，继续已有会话
    - 如果不提供，系统自动创建新会话
    - 会话中的知识库配置会被保存
    
    ### 错误码
    - **400**: 请求参数错误
    - **401**: 未认证或会话已过期
    - **500**: 服务器内部错误
    """,
             responses={
                 200: {
                     "description": "对话成功",
                     "content": {
                         "application/json": {
                             "example": {
                                 "success": True,
                                 "message": "根据您提供的数据分析，我发现以下趋势...",
                                 "data": {
                                     "session_id": "session_123",
                                     "timestamp": "2024-01-01T12:00:00",
                                     "user_message": "请帮我分析销售数据",
                                     "knowledge_base_ids": ["kb_001"]
                                 }
                             }
                         }
                     }
                 },
                 400: {
                     "description": "请求参数错误",
                     "content": {
                         "application/json": {
                             "example": {"detail": "消息内容不能为空"}
                         }
                     }
                 },
                 401: {
                     "description": "未认证",
                     "content": {
                         "application/json": {
                             "example": {"detail": "未认证或会话已过期"}
                         }
                     }
                 }
             }
             )
async def chat(request: ChatRequest, _: User = Depends(require_auth)):
    """发送聊天消息"""
    try:
        # 获取或创建会话ID
        session_id = get_or_create_session_id(request.session_id)
        logger.info(f"会话Id: {session_id}")

        # 获取会话信息以获取已配置的知识库
        session_obj = await session_manager.get_session(session_id)
        session_knowledge_bases = []

        if session_obj:
            session_knowledge_bases = session_obj.get_knowledge_base_ids()

        # 确定要使用的知识库ID列表
        # 优先级：请求中的知识库 > 会话配置的知识库 > 无指定
        knowledge_base_ids = request.knowledge_base_ids or session_knowledge_bases

        # 如果请求中有知识库配置且与会话不同，更新会话配置
        if request.knowledge_base_ids and request.knowledge_base_ids != session_knowledge_bases:
            await session_manager.update_session_knowledge_bases(session_id, request.knowledge_base_ids)
            knowledge_base_ids = request.knowledge_base_ids

        # 确保会话存在于数据库中
        await session_manager.create_session(session_id, knowledge_base_ids)

        # 更新用户消息活动
        await session_manager.update_session_activity(
            session_id,
            request.message,
            "user"
        )

        # 处理AI回复
        ai_response = await process_ai_query(
            request.message,
            session_id,
            knowledge_base_ids  # 使用确定的知识库ID列表
        )

        # 更新AI回复活动
        await session_manager.update_session_activity(
            session_id,
            ai_response,
            "assistant"
        )

        return ChatResponse(
            success=True,
            message=ai_response,
            data=ChatResponseData(
                session_id=session_id,
                timestamp=datetime.now().isoformat(),
                user_message=request.message,
                knowledge_base_ids=knowledge_base_ids
            )
        )

    except Exception as e:
        logger.exception(f"聊天处理失败: {e}")
        raise HTTPException(status_code=500, detail=f"聊天处理失败: {str(e)}")


@router.get("/sessions",
            response_model=SessionListResponse,
            summary="获取会话列表",
            description="""
    ## 获取会话列表接口
    
    获取当前用户的所有聊天会话。
    
    ### 功能特点
    - 分页获取会话列表
    - 显示会话基本信息和统计数据
    - 包含最后消息和活动时间
    
    ### 查询参数
    - **limit**: 返回数量限制（默认50）
    - **offset**: 分页偏移量（默认0）
    
    ### 返回信息
    - 会话ID和创建时间
    - 最后活动时间
    - 消息总数
    - 最后一条消息内容
    - 关联的知识库信息
    
    ### 错误码
    - **401**: 未认证或会话已过期
    - **500**: 服务器内部错误
    """,
            responses={
                200: {
                    "description": "获取会话列表成功",
                    "content": {
                        "application/json": {
                            "example": {
                                "success": True,
                                "data": [
                                    {
                                        "id": "session_123",
                                        "created_at": "2024-01-01T10:00:00",
                                        "last_activity": "2024-01-01T12:00:00",
                                        "message_count": 6,
                                        "last_message": "谢谢您的帮助",
                                        "last_message_role": "user",
                                        "knowledge_base_ids": ["kb_001"]
                                    }
                                ],
                                "total": 1
                            }
                        }
                    }
                }
            }
            )
async def get_sessions(limit: int = 50, offset: int = 0, current_user: User = Depends(require_auth)):
    """获取所有会话列表"""
    try:
        # 从数据库获取会话列表
        db_sessions = await session_manager.get_all_sessions(limit=limit, offset=offset)

        sessions = []
        for db_session in db_sessions:
            sessions.append({
                "id": db_session.session_id,
                "created_at": db_session.created_at.isoformat(),
                "last_activity": db_session.last_activity.isoformat(),
                "message_count": db_session.message_count,
                "last_message": db_session.last_message,
                "last_message_role": db_session.last_message_role,
                "knowledge_base_ids": db_session.get_knowledge_base_ids()  # 新增：返回会话的知识库配置
            })

        return SessionListResponse(success=True, data=sessions, total=len(sessions))

    except Exception as e:
        logger.exception(f"获取会话列表失败: {e}")
        raise HTTPException(status_code=500, detail=f"获取会话列表失败: {str(e)}")


@router.post("/{session_id}/history",
             response_model=ChatHistoryResponse,
             summary="获取聊天历史",
             description="""
    ## 获取聊天历史接口
    
    获取指定会话的完整聊天记录。
    
    ### 功能特点
    - 分页获取历史消息
    - 按时间倒序排列
    - 包含用户和AI的所有消息
    
    ### 路径参数
    - **session_id**: 会话ID
    
    ### 请求体参数
    - **limit**: 返回消息数量（1-100，默认50）
    - **offset**: 分页偏移量（默认0）
    
    ### 错误码
    - **401**: 未认证或会话已过期
    - **404**: 会话不存在
    - **500**: 服务器内部错误
    """,
             responses={
                 200: {
                     "description": "获取聊天历史成功",
                     "content": {
                         "application/json": {
                             "example": {
                                 "success": True,
                                 "message": "获取聊天历史成功",
                                 "data": {
                                     "session_id": "session_123",
                                     "messages": [
                                         {
                                             "id": "msg_001",
                                             "role": "user",
                                             "content": "你好",
                                             "timestamp": "2024-01-01T10:00:00",
                                             "session_id": "session_123"
                                         },
                                         {
                                             "id": "msg_002",
                                             "role": "assistant",
                                             "content": "您好！我是AI助手，有什么可以帮助您的吗？",
                                             "timestamp": "2024-01-01T10:00:05",
                                             "session_id": "session_123"
                                         }
                                     ]
                                 }
                             }
                         }
                     }
                 }
             }
             )
async def get_chat_history(session_id: str, request: ChatHistoryRequest, current_user: User = Depends(require_auth)):
    """获取指定会话的聊天历史"""
    try:
        # 使用ChatInstance获取数据库中的历史记录
        chat_instance = ChatInstance(session_id)
        db_messages = await chat_instance.get_chat_history(
            limit=request.limit,
            offset=request.offset
        )

        # 转换为ChatMessage格式
        chat_messages = []
        for db_msg in db_messages:
            # 根据LlamaIndex ChatMessage的具体结构调整
            if hasattr(db_msg, 'content') and hasattr(db_msg, 'role'):
                # 获取消息内容和角色
                content = db_msg.content if isinstance(db_msg.content, str) else str(db_msg.content)
                role = db_msg.role if hasattr(db_msg, 'role') else 'assistant'

                # 处理时间戳
                timestamp = datetime.now()
                if hasattr(db_msg, 'timestamp'):
                    timestamp = db_msg.timestamp
                elif hasattr(db_msg, 'created_at'):
                    timestamp = db_msg.created_at

                chat_messages.append(ChatMessage(
                    id=str(uuid.uuid4()),  # 生成唯一ID
                    role=role,
                    content=content,
                    timestamp=timestamp,
                    session_id=session_id
                ))

        # 按时间排序，确保消息顺序正确
        chat_messages.sort(key=lambda x: x.timestamp)

        return ChatHistoryResponse(
            success=True,
            message="获取聊天历史成功",
            data=ChatHistoryData(
                messages=chat_messages,
                session_id=session_id
            )
        )

    except Exception as e:
        logger.exception(f"获取聊天历史失败: {e}")
        raise HTTPException(status_code=500, detail=f"获取聊天历史失败: {str(e)}")


@router.post("/{session_id}/clear")
async def clear_session(session_id: str, current_user: User = Depends(require_auth)):
    """清空指定会话的聊天记录"""
    try:
        # 清空数据库中的会话记录
        # TODO: 需要实现清空ChatStore中对应session_id的记录
        # 这里需要调用RAGQueryEngine的清空方法或直接操作ChatStore

        # 重置会话的消息计数和最后消息
        await session_manager.update_session_activity(
            session_id,
            message_content="",
            message_role=None
        )

        # 同时清空缓存
        ChatInstance.clear_session_cache(session_id)

        return success_response(message="会话记录已清空")

    except Exception as e:
        logger.exception(f"清空会话失败: {e}")
        raise HTTPException(status_code=500, detail=f"清空会话失败: {str(e)}")


@router.delete("/{session_id}")
async def delete_session(session_id: str, current_user: User = Depends(require_auth)):
    """删除指定会话"""
    try:
        # 删除数据库中的会话记录
        success = await session_manager.delete_session(session_id)

        if not success:
            raise HTTPException(status_code=404, detail="会话不存在")
        # 清空缓存
        ChatInstance.clear_session_cache(session_id)
        return success_response(message="会话已删除")

    except HTTPException:
        raise
    except Exception as e:
        logger.exception(f"删除会话失败: {e}")
        raise HTTPException(status_code=500, detail=f"删除会话失败: {str(e)}")


class NewSessionRequest(BaseModel):
    """新建会话请求模型"""
    knowledge_base_ids: Optional[List[str]] = None


@router.post("/new-session")
async def create_new_session(request: NewSessionRequest = NewSessionRequest(), current_user: User = Depends(require_auth)):
    """创建新会话"""
    try:
        session_id = str(uuid.uuid4())

        # 创建会话时可以指定知识库
        await session_manager.create_session(session_id, request.knowledge_base_ids)

        return success_response(
            data={
                "session_id": session_id,
                "knowledge_base_ids": request.knowledge_base_ids
            },
            message="新会话创建成功"
        )
    except Exception as e:
        logger.exception(f"创建新会话失败: {e}")
        raise HTTPException(status_code=500, detail=f"创建新会话失败: {str(e)}")


@router.get("/health")
async def chat_health_check():
    """聊天服务健康检查"""
    cache_info = ChatInstance.get_cache_info()
    return success_response(
        data={
            "status": "healthy",
            "timestamp": datetime.now().isoformat(),
            "cache_info": cache_info,
            "storage_type": "database_persistent",
        },
        message="服务健康状态良好")


@router.post("/admin/cleanup")
async def cleanup_old_sessions(days: int = 30, current_user: User = Depends(require_admin)):
    """管理员接口：清理旧会话"""
    try:
        deleted_count = await session_manager.clear_old_sessions(days)
        return success_response(
            data={"deleted_count": deleted_count},
            message=f"已清理 {deleted_count} 个旧会话"
        )
    except Exception as e:
        logger.exception(f"清理旧会话失败: {e}")
        raise HTTPException(status_code=500, detail=f"清理旧会话失败: {str(e)}")


@router.put("/{session_id}/knowledge-bases")
async def update_session_knowledge_bases(session_id: str, knowledge_base_ids: List[str], current_user: User = Depends(require_auth)):
    """更新会话的知识库配置"""
    try:
        success = await session_manager.update_session_knowledge_bases(session_id, knowledge_base_ids)

        if success:
            return success_response(
                data={
                    "session_id": session_id,
                    "knowledge_base_ids": knowledge_base_ids
                },
                message="会话知识库配置更新成功"
            )
        else:
            raise HTTPException(status_code=404, detail="会话不存在")

    except HTTPException:
        raise
    except Exception as e:
        logger.exception(f"更新会话知识库配置失败: {e}")
        raise HTTPException(status_code=500, detail=f"更新会话知识库配置失败: {str(e)}")


@router.get("/{session_id}/knowledge-bases")
async def get_session_knowledge_bases(session_id: str, current_user: User = Depends(require_auth)):
    """获取会话的知识库配置"""
    try:
        session_obj = await session_manager.get_session(session_id)

        if not session_obj:
            raise HTTPException(status_code=404, detail="会话不存在")

        return success_response(
            data={
                "session_id": session_id,
                "knowledge_base_ids": session_obj.get_knowledge_base_ids()
            },
            message="获取会话知识库配置成功"
        )

    except HTTPException:
        raise
    except Exception as e:
        logger.exception(f"获取会话知识库配置失败: {e}")
        raise HTTPException(status_code=500, detail=f"获取会话知识库配置失败: {str(e)}")
